﻿using CSRedis;
using Dora.Tools.Utility.Const;
using System;
using System.Threading.Tasks;

namespace Dora.Tools.Utility.Redis
{
    public class RedisManager
    {
        protected static string ConnectStrWrite = ConstValue.RedisConnectStrWrite;
        //protected static string ConnectStrRead = ConstValue.RedisConnectStrRead;

        //protected static CSRedisClient RdsWrite = null;
        //protected static CSRedisClient RdsRead = null;

        private static readonly object LockObjWrite = new object();
        //private static readonly object LockObjRead = new object();

        private const int DefaultTimeoutSeconds = 10800;// 默认的缓存过期时间，为3小时(10800秒)


        protected static CSRedisClient _rds = null;
        protected static CSRedisClient Rds
        {
            get
            {

                if (_rds == null)
                {
                    lock (LockObjWrite)
                    {
                        if (_rds == null)
                        {
                            _rds = new CSRedisClient(ConnectStrWrite);
                        }
                    }
                }

                return _rds;
            }
        }
        //public static CSRedisClient GetWriteClient()
        //{
        //    if (string.IsNullOrEmpty(ConnectStrWrite))
        //    {
        //        Console.WriteLine("写连接未设置");
        //    }


        //    if (RdsWrite == null)
        //    {
        //        lock (LockObjWrite)
        //        {
        //            if (RdsWrite == null)
        //            {
        //                RdsRead = RdsWrite = new CSRedisClient(ConnectStrWrite);
        //                Rds.Initialization(RdsWrite);
        //            }
        //        }
        //    }

        //    return RdsWrite;
        //}

        //public static CSRedisClient GetReadClient()
        //{
        //    return GetWriteClient();
        //    //if (string.IsNullOrEmpty(ConnectStrRead))
        //    //{
        //    //    Console.WriteLine("读连接未设置");
        //    //}

        //    //if (RdsRead == null)
        //    //{
        //    //    lock (LockObjRead)
        //    //    {
        //    //        if (RdsRead == null)
        //    //        {
        //    //            RdsRead = new CSRedisClient(ConnectStrRead);
        //    //            Rds.Initialization(RdsRead);
        //    //        }
        //    //    }
        //    //}
        //    //return RdsRead;
        //}




        //private string GetRedisConfig()
        //{
        //    var redisSettings = AppConfig.GetSection("CachingSettings:1:Properties:1:Maps:0:Properties:0:value").Value;
        //    if (!string.IsNullOrEmpty(redisSettings))
        //    {
        //        var pwd = redisSettings.Split('@')[0];
        //        var redisServer = redisSettings.Split('@')[1].Split(':');
        //        var redisServerHost = redisServer[0];
        //        var redisPort = redisServer[1];

        //        return $"{redisServerHost}:{redisPort},password={pwd},defaultDatabase=0,poolsize=50,ssl=false,writeBuffer=10240,prefix=";
        //    }

        //    return null;
        //}
        public static string Get(string key)
        {
            //if (RdsRead == null)
            //    RdsRead = GetReadClient();
            return Rds.Get(key);
        }
        public static T Get<T>(string key)
        {
            //if (RdsRead == null)
            //    RdsRead = GetReadClient();
            return Rds.Get<T>(key);
        }
        public static Task<T> GetAsync<T>(string key)
        {
            //if (RdsRead == null)
            //    RdsRead = GetReadClient();
            return Rds.GetAsync<T>(key);
        }
        public static Task<string> GetAsync(string key)
        {
            //if (RdsRead == null)
            //    RdsRead = GetReadClient();
            return Rds.GetAsync(key);
        }

        //public static Task<T> HMGetAsync<T>(string key, string[] fields)
        //{
        //    return Rds.HMGetAsync(key, fields);
        //}

        public static T HGet<T>(string key, string field)
        {
            //if (RdsRead == null)
            //    RdsRead = GetReadClient();
            return Rds.HGet<T>(key, field);
        }

        public static Task<T> HGetAsync<T>(string key, string field)
        {
            //if (RdsRead == null)
            //    RdsRead = GetReadClient();
            return Rds.HGetAsync<T>(key, field);
        }

        public static string HGet(string key, string field)
        {
            //if (RdsRead == null)
            //    RdsRead = GetReadClient();
            return Rds.HGet(key, field);
        }
        public static bool HSet(string key, string field, object value)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.HSet(key, field, value);
        }
        public static Task<bool> HSetAsync(string key, string field, object value)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.HSetAsync(key, field, value);
        }
        public static bool HSetNx(string key, string field, object value)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.HSet(key, field, value);
        }
        public static Task<bool> HSetNxAsync(string key, string field, object value)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.HSetNxAsync(key, field, value);
        }

        public static bool Set(string key, object value, int expireSeconds = -1, RedisExistence? exists = null)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.Set(key, value, expireSeconds, exists);
        }

        public static Task<bool> SetAsync(string key, object value, int expireSeconds = -1, RedisExistence? exists = null)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.SetAsync(key, value, expireSeconds, exists);
        }

        public static Task<bool> HmSetAsync(string key, object[] values)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.HMSetAsync(key, values);
        }

        /// <summary>
        /// 用于在 key 存在时删除 key
        /// </summary>
        /// <param name="key">key:不含prefix前辍</param>
        /// <returns></returns>
        public static long Del(params string[] key)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.Del(key);
        }

        /// <summary>
        /// 用于在 key 存在时删除 key
        /// </summary>
        /// <param name="key">key:不含prefix前辍</param>
        /// <returns></returns>
        public static Task<long> DelAsync(params string[] key)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.DelAsync(key);
        }

        public static long HDel(string key, params string[] fields)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.HDel(key, fields);
        }
        public static Task<long> HDelAsync(string key, params string[] fields)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.HDelAsync(key, fields);
        }
        public static bool Exists(string key)
        {
            //if (RdsRead == null)
            //    RdsRead = GetReadClient();
            return Rds.Exists(key);
        }
        public static Task<bool> ExistsAsync(string key)
        {
            //if (RdsRead == null)
            //    RdsRead = GetReadClient();
            return Rds.ExistsAsync(key);
        }
        public static bool HExists(string key, string field)
        {
            //if (RdsRead == null)
            //    RdsRead = GetReadClient();
            return Rds.HExists(key, field);
        }
        public static Task<bool> HExistsAsync(string key, string field)
        {
            //if (RdsRead == null)
            //    RdsRead = GetReadClient();
            return Rds.HExistsAsync(key, field);
        }


        public static bool Expire(string key, int seconds)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.Expire(key, seconds);

        }

        public static bool Expire(string key, TimeSpan expire)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.Expire(key, expire);
        }
        /// <summary>
        /// 异步设置key的过期时间 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="expire"></param>
        /// <returns></returns>
        public static Task<bool> ExpireAsync(string key, TimeSpan expire)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.ExpireAsync(key, expire);
        }

        /// <summary>
        /// 取消生存时间，将永不过期
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static Task<bool> PersistAsync(string key)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            return Rds.PersistAsync(key);
        }

        public static T CacheShell<T>(string key, int timeoutSeconds, Func<T> getData)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            var data = Rds.CacheShell<T>(key, (timeoutSeconds > 0 ? timeoutSeconds : DefaultTimeoutSeconds), getData);
            if (timeoutSeconds == -1)
                Rds.PersistAsync(key);
            return data;
        }

        public static (string key, T value)[] CacheShell<T>(string key, string[] fields, int timeoutSeconds, Func<string[], (string, T)[]> getData)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            var data = Rds.CacheShell<T>(key, fields, (timeoutSeconds > 0 ? timeoutSeconds : DefaultTimeoutSeconds), getData);
            if (timeoutSeconds == -1)
                Rds.PersistAsync(key);
            return data;
        }
        public static T CacheShell<T>(string key, string field, int timeoutSeconds, Func<T> getData)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            var data = Rds.CacheShell<T>(key, field, (timeoutSeconds > 0 ? timeoutSeconds : DefaultTimeoutSeconds), getData);
            if (timeoutSeconds == -1)
                Rds.PersistAsync(key);
            return data;
        }
        public static Task<T> CacheShellAsync<T>(string key, string field, int timeoutSeconds, Func<Task<T>> getDataAsync)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            var data = Rds.CacheShellAsync<T>(key, field, (timeoutSeconds > 0 ? timeoutSeconds : DefaultTimeoutSeconds), getDataAsync);
            if (timeoutSeconds == -1)
                Rds.PersistAsync(key);
            return data;
        }
        public static Task<T> CacheShellAsync<T>(string key, int timeoutSeconds, Func<Task<T>> getDataAsync)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            var data = Rds.CacheShellAsync<T>(key, (timeoutSeconds > 0 ? timeoutSeconds : DefaultTimeoutSeconds), getDataAsync);
            if (timeoutSeconds == -1)
                Rds.PersistAsync(key);
            return data;
        }
        public static Task<(string key, T value)[]> CacheShellAsync<T>(string key, string[] fields, int timeoutSeconds, Func<string[], Task<(string, T)[]>> getDataAsync)
        {
            //if (RdsWrite == null)
            //    RdsWrite = GetWriteClient();
            var data = Rds.CacheShellAsync<T>(key, fields, (timeoutSeconds > 0 ? timeoutSeconds : DefaultTimeoutSeconds), getDataAsync);
            if (timeoutSeconds == -1)
                Rds.PersistAsync(key);
            return data;
        }
    }

    //public class AppConfig
    //{

    //    internal static IConfigurationRoot Configuration { get; set; }



    //    public static IConfigurationSection GetSection(string name)
    //    {
    //        return AppConfig.Configuration?.GetSection(name);
    //    }


    //}

}